// Copyright (c) 2020-present, INSPUR Co, Ltd. All rights reserved.
// This source code is licensed under Apache 2.0 License.

#pragma once
#include "abstract_loadkey.h"
#include "tree_node.h"

namespace syn_art_fullkey {

class Tree {

private:
  N *const root_;

  ILoadKey *loadKey_;

public:
  Tree(ILoadKey *loadKey);

  Tree(const Tree &) = delete;
  Tree(Tree &&t) = delete;
  Tree &operator=(const Tree &) = delete;
  Tree &operator=(Tree &&) = delete;

  ~Tree();

  bool splitPrefix(uint32_t level, bool keyEnd, uint8_t keyToken, void *value,
                   N *&node, const rocksdb::Slice &samePrefix,
                   rocksdb::Slice &remainPrefix, N *parentNode,
                   uint8_t parentKey);

  static int matchPrefix(N *n, const rocksdb::Slice &k, uint32_t &level,
                         rocksdb::Slice &remainPrefix);

  bool insertOrGetLG(const rocksdb::Slice &k, void *newValue, void *&retValue);
  void *getLG(const rocksdb::Slice &key) {
    return this->seek(key, false, true);
  }
  void *get(const rocksdb::Slice &key) { return this->seek(key, true, false); }
  void *getEG(const rocksdb::Slice &key) { return this->seek(key, true, true); }

  void checkAnyChildrenLocked(N *node) const;

private:
  // current node min in void*.
  void *getMinTID(N *node, uint8_t start) const;
  // current node max key in void*.
  void *getMaxTID(N *node, uint8_t end) const;
  void *seek(const rocksdb::Slice &k, bool equal, bool greater) const;
  void *seekChildren(N *node, const rocksdb::Slice &k, uint32_t level,
                     bool equal, bool greater) const;
};
} // namespace syn_art_fullkey
